package com.aaron.remoting.handler;

import com.aaron.exception.RpcException;
import com.aaron.factory.SingletonFactory;
import com.aaron.provider.ServiceProvider;
import com.aaron.provider.impl.ZkServiceProviderImpl;
import com.aaron.remoting.dto.RpcRequest;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

// 处理RPC请求，根据rpc请求调用目标类的目标方法.使用的是动态代理。
// RpcServerHandler中使用该类，调用其方法
@Slf4j
public class RpcRequestHandler {
    private final ServiceProvider serviceProvider;

    public RpcRequestHandler() {
        serviceProvider = SingletonFactory.getInstance(ZkServiceProviderImpl.class);
    }

    // 调用相应的方法，然后返回该方法
    public Object handle(RpcRequest rpcRequest) {
        Object service = serviceProvider.getService(rpcRequest.getRpcServiceName());
        return invokeTargetMethod(rpcRequest, service);
    }

    // 获取方法的执行结果，给传输的信息和服务对象。服务对象执行传输的信息，得到结果
    private Object invokeTargetMethod(RpcRequest rpcRequest, Object service) {
        Object result;
        try {
            Method method = service.getClass().getMethod(rpcRequest.getMethodName(), rpcRequest.getParamTypes());
            // 反射去执行
            result = method.invoke(service, rpcRequest.getParameters());
            log.info("service:[{}] successful invoke method:[{}]", rpcRequest.getInterfaceName(), rpcRequest.getMethodName());
        } catch (NoSuchMethodException | IllegalArgumentException | InvocationTargetException | IllegalAccessException e) {
            throw new RpcException(e.getMessage(), e);
        }
        return result;
    }
}
